/*
 * File    : TorrentImpl.java
 * Created : 08-Dec-2003
 * By      : parg
 * 
 * Azureus - a Java Bittorrent client
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details ( see the LICENSE file ).
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package org.gudy.azureus2.pluginsimpl.local.torrent;

import java.net.*;

/**
 * @author parg
 *
 */

import java.util.Map;
import java.io.File;

//import org.gudy.azureus2.core3.download.DownloadManagerState;
//import org.gudy.azureus2.core3.download.DownloadManagerStateFactory;
//import org.gudy.azureus2.core3.internat.*;
//import org.gudy.azureus2.core3.logging.LogRelation;
import org.gudy.azureus2.core3.internat.LocaleTorrentUtil;
import org.gudy.azureus2.core3.internat.LocaleUtilDecoder;
import org.gudy.azureus2.core3.torrent.*;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.plugins.PluginInterface;
import org.gudy.azureus2.plugins.torrent.*;
import org.gudy.azureus2.plugins.download.*;
//import org.gudy.azureus2.pluginsimpl.locale.download.*;

//import org.torrent.transfer.TransferImpl;
//import com.aelitis.azureus.plugins.magnet.MagnetPlugin;

public class 
TorrentImpl
//	extends LogRelation
	implements Torrent
{
//	private static MagnetPlugin		magnet_plugin;
	
	private PluginInterface			pi;
	private TOTorrent				torrent;
	private LocaleUtilDecoder		decoder;
	
	private boolean					complete;
	
	public
	TorrentImpl(
		TOTorrent		_torrent )
	{
		this( null, _torrent );
	}
	
	public
	TorrentImpl(
		PluginInterface	_pi,
		TOTorrent		_torrent )
	{
		pi		= _pi;
		torrent	= _torrent;
	}
	
//	public String
//	getName()
//	{
//		String	name = decode( torrent.getName());
//
//		name = FileUtil.convertOSSpecificChars( name, false );
//
//		return( name );
//	}
	
	public URL
	getAnnounceURL()
	{
		return( torrent.getAnnounceURL());
	}
	
	public void
	setAnnounceURL(
		URL		url )
	{
		torrent.setAnnounceURL( url );
		
		updated();
	}
//
//	public TorrentAnnounceURLList
//	getAnnounceURLList()
//	{
//		return( new TorrentAnnounceURLListImpl( this ));
//	}

	public TOTorrent
	getTorrent()
	{
		return( torrent );
	}
	
//	public boolean
//	isDecentralised()
//	{
//		return( TorrentUtils.isDecentralised( torrent ));
//	}
//	public boolean
//	isDecentralisedBackupEnabled()
//	{
//		return( TorrentUtils.getDHTBackupEnabled( torrent ));
//	}
//
//	public void
//	setDecentralisedBackupRequested(
//		boolean	requested )
//	{
//		TorrentUtils.setDHTBackupRequested( torrent, requested );
//	}
//
//	public boolean
//	isDecentralisedBackupRequested()
//	{
//		return( TorrentUtils.isDHTBackupRequested( torrent ));
//
//	}
//	public boolean
//	isPrivate()
//	{
//		return( TorrentUtils.getPrivate( torrent ));
//	}
//
//	public void
//	setPrivate(
//		boolean	priv )
//	{
//		TorrentUtils.setPrivate( torrent, priv );
//	}
//
//	public boolean
//	wasCreatedByUs()
//	{
//		return( TorrentUtils.isCreatedTorrent( torrent ));
//	}
//
//	public URL
//	getMagnetURI()
//
//		throws TorrentException
//	{
//		if ( magnet_plugin == null ){
//
//			PluginInterface magnet_pi = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByClass( MagnetPlugin.class );
//
//			if ( magnet_pi != null ){
//
//				 magnet_plugin = (MagnetPlugin)magnet_pi.getPlugin();
//			}
//		}
//
//		if ( magnet_plugin == null ){
//
//			throw( new TorrentException( "MegnetPlugin unavailable" ));
//		}
//
//		try{
//			URL	res = magnet_plugin.getMagnetURL(  torrent.getHash());
//
//			return( res );
//
//		}catch( TOTorrentException e ){
//
//			throw( new TorrentException(e ));
//		}
//	}
	
	public byte[]
	getHash()
	{
		try{
			return( torrent.getHash());
			
		}catch( TOTorrentException e ){
			
//			Debug.printStackTrace( e );
			
			return( null );
		}
	}
		
	public long
	getSize()
	{
		return( torrent.getSize());
	}
	
//	public String
//	getComment()
//	{
//		return( decode(torrent.getComment()));
//	}
	
	public void
	setComment(
		String	comment )
	{
		torrent.setComment( comment );
	}
	public long
	getCreationDate()
	{
		return( torrent.getCreationDate());
	}
	
//	public String
//	getCreatedBy()
//	{
//		return( decode( torrent.getCreatedBy()));
//	}
	

	public long
	getPieceSize()
	{
		return( torrent.getPieceLength());
	}
	
	public long
	getPieceCount()
	{
		return( torrent.getNumberOfPieces());
	}
	
	public byte[][]
  	getPieces()
  	{
		try{
			return( torrent.getPieces());
			
		}catch( TOTorrentException e ){
			
//			Debug.printStackTrace( e );
			
			return( new byte[0][0] );
		}
  	}	
	          	
//	public TorrentFile[]
//	getFiles()
//	{
//		TOTorrentFile[]	files = torrent.getFiles();
//
//		TorrentFile[]	res = new TorrentFile[files.length];
//
//		for (int i=0;i<res.length;i++){
//
//			TOTorrentFile	tf = files[i];
//
//			byte[][]	comps = tf.getPathComponents();
//
//			String	name = "";
//
//			for (int j=0;j<comps.length;j++){
//
//				String	comp = decode(comps[j]);
//
//				comp = FileUtil.convertOSSpecificChars( comp, j != comps.length-1 );
//
//				name += (j==0?"":File.separator)+comp;
//			}
//
//			res[i] = new TorrentFileImpl(name, tf.getLength());
//		}
//
//		return( res );
//	}
//
	protected void
	getDecoder()
	{
			// We defer the getting of the decoder until it is required as this Torrent may have been
			// created in order to simply remove additional properties from it before serialising it
			// Indeed, this was happening and unfortunately resulting in 1) the encoding being
			// serialised 2) the user being prompted for an encoding choice

		try{
			decoder = LocaleTorrentUtil.getTorrentEncoding( torrent );

		}catch( Throwable e ){

		}
	}
//
//	public String
//	getEncoding()
//	{
//		getDecoder();
//
//		if ( decoder != null ){
//
//			return( decoder.getName());
//		}
//
//		return( Constants.DEFAULT_ENCODING );
//	}
//
//	public void
//	setEncoding(String encoding)throws TorrentEncodingException {
//		try {
//			LocaleTorrentUtil.setTorrentEncoding(torrent, encoding);
//		} catch(LocaleUtilEncodingException e) {
//			throw new TorrentEncodingException("Failed to set the encoding",e);
//		}
//	}
//
//	public void
//	setDefaultEncoding() throws TorrentEncodingException {
//		setEncoding(Constants.DEFAULT_ENCODING);
//	}
//
	protected String
	decode(
		byte[]		data )
	{
		getDecoder();

		if ( data != null ){

			if ( decoder != null ){

				try{
					return( decoder.decodeString(data));

				}catch( Throwable e ){
				}
			}

			return( new String(data));
		}

		return( "" );
	}
//
//	public Object
//	getAdditionalProperty(
//		String		name )
//	{
//		return( torrent.getAdditionalProperty( name ));
//	}
//
//	public Torrent
//	removeAdditionalProperties()
//	{
//		try{
//			TOTorrent	t = TOTorrentFactory.deserialiseFromMap(torrent.serialiseToMap());
//
//			t.removeAdditionalProperties();
//
//			return( new TorrentImpl( t ));
//
//		}catch( TOTorrentException e ){
//
//			Debug.printStackTrace(e);
//
//			return( this );
//		}
//	}
//
//	public void
//	setPluginStringProperty(
//		String		name,
//		String		value )
//	{
//		PluginInterface	p = pi;
//
//		if ( p == null ){
//
//			p = UtilitiesImpl.getPluginThreadContext();
//		}
//
//		if ( p == null ){
//
//			name = "<internal>." + name;
//
//		}else{
//
//			name = p.getPluginID() + "." + name;
//		}
//
//		TorrentUtils.setPluginStringProperty( torrent, name, value );
//	}
//
//	public String
//	getPluginStringProperty(
//		String		name )
//	{
//		PluginInterface	p = pi;
//
//		if ( p == null ){
//
//			p = UtilitiesImpl.getPluginThreadContext();
//		}
//
//		if ( p == null ){
//
//			name = "<internal>." + name;
//
//		}else{
//
//			name = p.getPluginID() + "." + name;
//		}
//
//		return( TorrentUtils.getPluginStringProperty( torrent, name ));
//	}
//
//	public void
//	setMapProperty(
//		String		name,
//		Map			value )
//	{
//		TorrentUtils.setPluginMapProperty( torrent, name, value );
//	}
//
//	public Map
//	getMapProperty(
//		String		name )
//	{
//		return( TorrentUtils.getPluginMapProperty( torrent, name ));
//	}
	
	public Map
	writeToMap()
	
		throws TorrentException
	{
		try{
			return( torrent.serialiseToMap());
			
		}catch( TOTorrentException e ){
			
			throw( new TorrentException( "Torrent::writeToMap: fails", e ));
		}
	}
	
	public byte[]
	writeToBEncodedData()
	
		throws TorrentException
	{
		try{
			Map	map = torrent.serialiseToMap();
			
			return( BEncoder.encode( map ));
			
		}catch( Throwable e ){
			
			throw( new TorrentException( "Torrent::writeToBEncodedData: fails", e ));
		}
	}	
	
	public void
	writeToFile(
		File		file )
	
		throws TorrentException
	{
		try{
				// don't use TorrentUtils.writeToFile as this updates the internal torrent
				// file reference an means that the torrent get's auto-written to the new
				// location in future, most likley NOT the desired behaviour
			
			torrent.serialiseToBEncodedFile( file );
			
		}catch( TOTorrentException e ){
			
			throw( new TorrentException( "Torrent::writeToFile: fails", e ));
		}
	}
  
 	protected void
	updated()
	{
//		try{
//			DownloadImpl dm = (DownloadImpl)DownloadManagerImpl.getDownloadStatic( torrent );
//
//			if ( dm != null ){
//
//				dm.torrentChanged();
//			}
//                    DownloadImpl dm = (DownloadImpl)DownloadManagerImpl.getDownloadStatic( torrent );
//                    TransferImpl dm = (TransferImpl)DownloadManagerImpl.getDownloadStatic( torrent );
//			if ( dm != null ){
                                System.out.println("torrent Changed has to be called");
//				dm.torrentChanged();
//			}
//		}catch( DownloadException e ){
//
//			// torrent may not be running
//		}
	}
//
//	public void
//	save()
//		throws TorrentException
//	{
//		try{
//			TorrentUtils.writeToFile( torrent );
//
//		}catch( TOTorrentException e ){
//
//			throw( new TorrentException( "Torrent::save Fails", e ));
//		}
//	}
//
//	public void
//	setComplete(
//		File		data_dir )
//
//		throws TorrentException
//	{
//		try{
//			LocaleTorrentUtil.setDefaultTorrentEncoding( torrent );
//
//			DownloadManagerState	download_manager_state =
//				DownloadManagerStateFactory.getDownloadState( torrent );
//
//			TorrentUtils.setResumeDataCompletelyValid( download_manager_state );
//
//			download_manager_state.save();
//
//			complete	= true;
//
//		}catch( Throwable e ){
//
//			throw( new TorrentException("encoding selection fails", e ));
//		}
//	}
	
	public boolean
	isComplete()
	{
			// TODO: could check the download state too I guess...
		
		return( complete );
	}
	
	
  // Pass LogRelation off to core objects

//	/* (non-Javadoc)
//	 * @see org.gudy.azureus2.core3.logging.LogRelation#getLogRelationText()
//	 */
//	public String getRelationText() {
//		return propogatedRelationText(torrent);
//	}

	/* (non-Javadoc)
	 * @see org.gudy.azureus2.core3.logging.LogRelation#getQueryableInterfaces()
	 */
	public Object[] getQueryableInterfaces() {
		return new Object[] { torrent };
	}
	
	public boolean isSimpleTorrent() {return torrent.isSimpleTorrent();}

    public String
	getName()
	{
		String	name = decode( torrent.getName());

		name = FileUtil.convertOSSpecificChars( name, false );

		return( name );
	}


    @Override
    public TorrentAnnounceURLList getAnnounceURLList() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public String getComment() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public String getCreatedBy() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public TorrentFile[] getFiles() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public String getEncoding() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void setEncoding(String encoding) throws TorrentEncodingException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void setDefaultEncoding() throws TorrentEncodingException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Object getAdditionalProperty(String name) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Torrent removeAdditionalProperties() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void setPluginStringProperty(String name, String value) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public String getPluginStringProperty(String name) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void setMapProperty(String name, Map value) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Map getMapProperty(String name) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public boolean isDecentralised() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public boolean isDecentralisedBackupEnabled() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void setDecentralisedBackupRequested(boolean requested) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public boolean isDecentralisedBackupRequested() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public boolean isPrivate() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void setPrivate(boolean priv) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public boolean wasCreatedByUs() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public URL getMagnetURI() throws TorrentException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void save() throws TorrentException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void setComplete(File data_dir) throws TorrentException {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}